//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//

package cn.intotw.rdcj.core.config.mybatis.dialect;


import java.beans.PropertyDescriptor;
import java.sql.DatabaseMetaData;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import javax.sql.DataSource;
import net.sf.jsqlparser.expression.Alias;
import net.sf.jsqlparser.expression.Function;
import net.sf.jsqlparser.parser.CCJSqlParserUtil;
import net.sf.jsqlparser.schema.Column;
import net.sf.jsqlparser.statement.Statement;
import net.sf.jsqlparser.statement.select.FromItem;
import net.sf.jsqlparser.statement.select.Join;
import net.sf.jsqlparser.statement.select.LateralSubSelect;
import net.sf.jsqlparser.statement.select.OrderByElement;
import net.sf.jsqlparser.statement.select.PlainSelect;
import net.sf.jsqlparser.statement.select.Select;
import net.sf.jsqlparser.statement.select.SelectBody;
import net.sf.jsqlparser.statement.select.SelectExpressionItem;
import net.sf.jsqlparser.statement.select.SelectItem;
import net.sf.jsqlparser.statement.select.SetOperationList;
import net.sf.jsqlparser.statement.select.SubJoin;
import net.sf.jsqlparser.statement.select.SubSelect;
import net.sf.jsqlparser.statement.select.ValuesList;
import net.sf.jsqlparser.statement.select.WithItem;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanWrapper;
import org.springframework.beans.BeanWrapperImpl;

public class Dialect {
    private static final List<SelectItem> COUNT_ITEM = new ArrayList();
    private static final Alias TABLE_ALIAS;
    private Map<String, String> CACHE = new ConcurrentHashMap();
    private String name;

    public Dialect(String name) {
        this.name = name;
    }

    public static Dialect createDialect(String driverName) {
        if (StringUtils.containsIgnoreCase(driverName, "mysql")) {
            return new MySQLDialect("mysql");
        } else if (StringUtils.containsIgnoreCase(driverName, "oracle")) {
            return new OracleDialect("oracle");
        } else if (StringUtils.containsIgnoreCase(driverName, "sqlserver")) {
            return new SQLServerDialect("sqlserver");
        } else if (StringUtils.containsIgnoreCase(driverName, "postgresql")) {
            return new PostgreSQLDialect("postgresql");
        } else if (StringUtils.containsIgnoreCase(driverName, "db2")) {
            return new DB2Dialect("db2");
        } else if (StringUtils.containsIgnoreCase(driverName, "hsqldb")) {
            return new HSQLDialect("hsqldb");
        } else if (StringUtils.containsIgnoreCase(driverName, "h2")) {
            return new H2Dialect("h2");
        } else if (StringUtils.containsIgnoreCase(driverName, "sqlite")) {
            return new Dialect("sqllite");
        } else if (StringUtils.containsIgnoreCase(driverName, "sybase")) {
            return new Dialect("sybase");
        } else {
            return StringUtils.containsIgnoreCase(driverName, "informix-sqli") ? new Dialect("informix") : new Dialect("unknown");
        }
    }

    public static Dialect createDialect(DatabaseMetaData databaseMetaData) throws SQLException {
        return createDialect(databaseMetaData.getDriverName().toLowerCase());
    }

    public static Dialect createDialect(DataSource dataSource) {
        String jdbcUrl = getJdbcUrl(dataSource);
        if (StringUtils.contains(jdbcUrl, ":mysql:")) {
            return new MySQLDialect("mysql");
        } else if (StringUtils.contains(jdbcUrl, ":oracle:")) {
            return new OracleDialect("oracle");
        } else if (StringUtils.contains(jdbcUrl, ":sqlserver://")) {
            return new SQLServerDialect("sqlserver");
        } else if (StringUtils.contains(jdbcUrl, ":postgresql:")) {
            return new PostgreSQLDialect("postgresql");
        } else if (StringUtils.contains(jdbcUrl, ":db2:")) {
            return new DB2Dialect("db2");
        } else if (StringUtils.contains(jdbcUrl, ":hsqldb:")) {
            return new HSQLDialect("hsqldb");
        } else if (StringUtils.contains(jdbcUrl, ":h2:")) {
            return new H2Dialect("h2");
        } else if (StringUtils.contains(jdbcUrl, ":sqlite:")) {
            return new Dialect("sqllite");
        } else if (StringUtils.contains(jdbcUrl, ":sybase:")) {
            return new Dialect("sybase");
        } else {
            return StringUtils.contains(jdbcUrl, ":informix-sqli:") ? new Dialect("informix") : new Dialect("unknown");
        }
    }

    public static String getJdbcUrl(DataSource dataSource) {
        List cache = new ArrayList();
        return getJdbcUrlInner(dataSource, cache);
    }

    private static String getJdbcUrlInner(Object o, List cache) {
        BeanWrapper beanWrapper = new BeanWrapperImpl(o);
        PropertyDescriptor[] descriptor = beanWrapper.getPropertyDescriptors();

        for(int i = 0; i < descriptor.length; ++i) {
            Class propertyType = descriptor[i].getPropertyType();
            if ((DataSource.class.isAssignableFrom(propertyType) || String.class.isAssignableFrom(propertyType)) && beanWrapper.isReadableProperty(descriptor[i].getName())) {
                Object value = beanWrapper.getPropertyValue(descriptor[i].getName());
                if (value != null && !cache.contains(value)) {
                    cache.add(value);
                    if (value instanceof String) {
                        if (StringUtils.contains((String)value, "jdbc:")) {
                            return (String)value;
                        }
                    } else {
                        String url = getJdbcUrlInner(value, cache);
                        if (url != null) {
                            return url;
                        }
                    }
                }
            }
        }

        return null;
    }

    public String getSequenceSql(String sequenceName) {
        return "select nextval('" + sequenceName + "') from dual";
    }

    public String getCountSql(String sql) {
        return this.getSmartCountSql(sql);
    }

    public final String getPageSql(String sql, int pageNo, int pageSize) {
        return this.getPageSqlInner(sql, (pageNo - 1) * pageSize, pageSize);
    }

    protected String getPageSqlInner(String sql, int offset, int limit) {
        throw new UnsupportedOperationException(this.name + " do not support paging query");
    }

    private String getSimpleCountSql(String sql) {
        return "select count(1) from (" + sql + ") tmp_count";
    }

    private String getSmartCountSql(String sql) {
        if (this.CACHE.get(sql) != null) {
            return (String)this.CACHE.get(sql);
        } else {
            Statement stmt = null;

            try {
                stmt = CCJSqlParserUtil.parse(sql);
            } catch (Throwable var6) {
                String countSql = this.getSimpleCountSql(sql);
                this.CACHE.put(sql, countSql);
                return countSql;
            }

            Select select = (Select)stmt;
            SelectBody selectBody = select.getSelectBody();
            this.processSelectBody(selectBody);
            this.processWithItemsList(select.getWithItemsList());
            this.sqlToCount(select);
            String result = select.toString();
            this.CACHE.put(sql, result);
            return result;
        }
    }

    private boolean isSimpleCount(PlainSelect select) {
        if (select.getGroupByColumnReferences() != null) {
            return false;
        } else if (select.getDistinct() != null) {
            return false;
        } else {
            Iterator var2 = select.getSelectItems().iterator();

            SelectItem item;
            do {
                if (!var2.hasNext()) {
                    return true;
                }

                item = (SelectItem)var2.next();
                if (item.toString().contains("?")) {
                    return false;
                }
            } while(!(item instanceof SelectExpressionItem) || !(((SelectExpressionItem)item).getExpression() instanceof Function));

            return false;
        }
    }

    private void sqlToCount(Select select) {
        SelectBody selectBody = select.getSelectBody();
        if (selectBody instanceof PlainSelect && this.isSimpleCount((PlainSelect)selectBody)) {
            ((PlainSelect)selectBody).setSelectItems(COUNT_ITEM);
        } else {
            PlainSelect plainSelect = new PlainSelect();
            SubSelect subSelect = new SubSelect();
            subSelect.setSelectBody(selectBody);
            subSelect.setAlias(TABLE_ALIAS);
            plainSelect.setFromItem(subSelect);
            plainSelect.setSelectItems(COUNT_ITEM);
            select.setSelectBody(plainSelect);
        }

    }

    private void processSelectBody(SelectBody selectBody) {
        if (selectBody instanceof PlainSelect) {
            this.processPlainSelect((PlainSelect)selectBody);
        } else if (selectBody instanceof WithItem) {
            WithItem withItem = (WithItem)selectBody;
            if (withItem.getSelectBody() != null) {
                this.processSelectBody(withItem.getSelectBody());
            }
        } else {
            SetOperationList operationList = (SetOperationList)selectBody;
            if (operationList.getSelects() != null && operationList.getSelects().size() > 0) {
                List<SelectBody> selects = operationList.getSelects();
                Iterator var4 = selects.iterator();

                while(var4.hasNext()) {
                    SelectBody select = (SelectBody)var4.next();
                    if (select instanceof PlainSelect) {
                        this.processPlainSelect((PlainSelect)select);
                    }
                }
            }

            if (!this.orderByHashParameters(operationList.getOrderByElements())) {
                operationList.setOrderByElements((List)null);
            }
        }

    }

    private void processPlainSelect(PlainSelect plainSelect) {
        if (!this.orderByHashParameters(plainSelect.getOrderByElements())) {
            plainSelect.setOrderByElements((List)null);
        }

        if (plainSelect.getFromItem() != null) {
            this.processFromItem(plainSelect.getFromItem());
        }

        if (plainSelect.getJoins() != null && plainSelect.getJoins().size() > 0) {
            List<Join> joins = plainSelect.getJoins();
            Iterator var3 = joins.iterator();

            while(var3.hasNext()) {
                Join join = (Join)var3.next();
                if (join.getRightItem() != null) {
                    this.processFromItem(join.getRightItem());
                }
            }
        }

    }

    private void processWithItemsList(List<WithItem> withItemsList) {
        if (withItemsList != null && withItemsList.size() > 0) {
            Iterator var2 = withItemsList.iterator();

            while(var2.hasNext()) {
                WithItem item = (WithItem)var2.next();
                this.processSelectBody(item.getSelectBody());
            }
        }

    }

    private void processFromItem(FromItem fromItem) {
        if (fromItem instanceof SubJoin) {
            SubJoin subJoin = (SubJoin)fromItem;
            if (subJoin.getJoin() != null && subJoin.getJoin().getRightItem() != null) {
                this.processFromItem(subJoin.getJoin().getRightItem());
            }

            if (subJoin.getLeft() != null) {
                this.processFromItem(subJoin.getLeft());
            }
        } else if (fromItem instanceof SubSelect) {
            SubSelect subSelect = (SubSelect)fromItem;
            if (subSelect.getSelectBody() != null) {
                this.processSelectBody(subSelect.getSelectBody());
            }
        } else if (!(fromItem instanceof ValuesList) && fromItem instanceof LateralSubSelect) {
            LateralSubSelect lateralSubSelect = (LateralSubSelect)fromItem;
            if (lateralSubSelect.getSubSelect() != null) {
                SubSelect subSelect = lateralSubSelect.getSubSelect();
                if (subSelect.getSelectBody() != null) {
                    this.processSelectBody(subSelect.getSelectBody());
                }
            }
        }

    }

    private boolean orderByHashParameters(List<OrderByElement> orderByElements) {
        if (orderByElements == null) {
            return false;
        } else {
            Iterator var2 = orderByElements.iterator();

            OrderByElement orderByElement;
            do {
                if (!var2.hasNext()) {
                    return false;
                }

                orderByElement = (OrderByElement)var2.next();
            } while(!orderByElement.toString().contains("?"));

            return true;
        }
    }

    static {
        COUNT_ITEM.add(new SelectExpressionItem(new Column("count(*)")));
        TABLE_ALIAS = new Alias("table_count");
        TABLE_ALIAS.setUseAs(false);
    }
}
